home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / networking / dumpnetworksetup / dumpnetworksetup.c next >
Encoding:
Text File  |  2000-06-23  |  31.4 KB  |  1,161 lines

  1. /*
  2.     File:        DumpNetworkSetup.c
  3.  
  4.     Contains:    Program to render Network Setup database as text.
  5.  
  6.     Written by: Quinn "The Eskimo!"    
  7.  
  8.     Copyright:    Copyright © 1998-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/22/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23.  
  24. // MoreIsBetter Setup
  25.  
  26. #include "MoreSetup.h"
  27.  
  28. // Pick up lots of OT interfaces.
  29.  
  30. #include <OpenTransport.h>
  31. #include <OpenTptInternet.h>
  32. #include <OpenTptLinks.h>
  33.  
  34. // Pick up standard system interfaces.
  35.  
  36. #include <CodeFragments.h>
  37. #include <Resources.h>
  38. #include <Errors.h>
  39. #include <Fonts.h>
  40. #include <Windows.h>
  41. #include <Menus.h>
  42. #include <TextEdit.h>
  43. #include <Dialogs.h>
  44. #include <StandardFile.h>
  45. #include <DateTimeUtils.h>
  46.  
  47. // Pick up ANSI C interfaces
  48.  
  49. #include <stdio.h>
  50. #include <FSp_fopen.h>
  51. #include <string.h>
  52.  
  53. // Pick up Network Setup stuff.
  54.  
  55. // Because I'm using a pre-release version of "NetworkSetup.h",
  56. // which is intended to be released as part of a future version of
  57. // Universal Interfaces, I have to define CALL_NOT_IN_CARBON myself
  58. // if it's not already been defined.
  59.  
  60. #ifndef CALL_NOT_IN_CARBON
  61.     #define CALL_NOT_IN_CARBON 1
  62. #endif
  63.  
  64. #include <NetworkSetup.h>
  65.  
  66. /////////////////////////////////////////////////////////////////
  67. #pragma mark ----- Binary to String  -----
  68.  
  69. static char gFormatInetHostBuffer[256];
  70.  
  71. static char *FormatInetHost(InetHost ipAddr)
  72.     // Non-reentrant, but I don't care.
  73. {
  74.     OTInetHostToString(ipAddr, gFormatInetHostBuffer);
  75.     return gFormatInetHostBuffer;
  76. }
  77.  
  78. static char *ClassToString(OSType class)
  79. {
  80.     switch (class) {
  81.         case kCfgClassAnyEntity:
  82.             return "kCfgClassAnyEntity";
  83.             break;
  84.         case kCfgClassUnknownEntity:
  85.             return "kCfgClassUnknownEntity";
  86.             break;
  87.         case kOTCfgClassNetworkConnection:
  88.             return "kOTCfgClassNetworkConnection";
  89.             break;
  90.         case kOTCfgClassGlobalSettings:
  91.             return "kOTCfgClassGlobalSettings";
  92.             break;
  93.         case kOTCfgClassServer:
  94.             return "kOTCfgClassServer";
  95.             break;
  96.         case kOTCfgClassSetOfSettings:
  97.             return "kOTCfgClassSetOfSettings";
  98.             break;
  99.         default:
  100.             return "unknown";
  101.     }
  102. }
  103.  
  104. static char *TypeToString(OSType class)
  105. {
  106.     switch (class) {
  107.         case kCfgTypeAnyEntity:
  108.             return "kCfgTypeAnyEntity";
  109.             break;
  110.         case kCfgTypeUnknownEntity:
  111.             return "kCfgTypeUnknownEntity";
  112.             break;
  113.         case kOTCfgTypeAppleTalk:
  114.             return "kOTCfgTypeAppleTalk";
  115.             break;
  116.         case kOTCfgTypeTCPv4:
  117.             return "kOTCfgTypeTCPv4";
  118.             break;
  119.         case kOTCfgTypeTCPv6:    
  120.             return "kOTCfgTypeTCPv6";
  121.             break;
  122.         case kOTCfgTypeRemote:    
  123.             return "kOTCfgTypeRemote";
  124.             break;
  125.         case kOTCfgTypeDial:
  126.             return "kOTCfgTypeDial";
  127.             break;
  128.         case kOTCfgTypeModem:    
  129.             return "kOTCfgTypeModem";
  130.             break;
  131.         case kOTCfgTypeInfrared:
  132.             return "kOTCfgTypeInfrared";
  133.             break;
  134.         case kOTCfgTypeSetOfSettings:
  135.             return "kOTCfgTypeSetOfSettings";
  136.             break;
  137.         case kOTCfgTypeDNS:
  138.             return "kOTCfgTypeDNS";
  139.             break;
  140.         case kOTCfgTypeGeneric:
  141.             return "kOTCfgTypeGeneric";
  142.             break;
  143.         default:
  144.             return "unknown";
  145.     }
  146. }
  147.  
  148. static char *TCPConfigMethodToString(UInt8 configMethod)
  149. {
  150.     switch (configMethod) {
  151.         case 0:
  152.             return "Manual";
  153.             break;
  154.         case 1:
  155.             return "RARP";
  156.             break;
  157.         case 2:
  158.             return "BOOTP";
  159.             break;
  160.         case 3:
  161.             return "DHCP";
  162.             break;
  163.         case 4:
  164.             return "MacIP";
  165.             break;
  166.         default:
  167.             return "unknown";
  168.     }
  169. }
  170.  
  171. static FILE *gOutput;
  172.  
  173. static void DefaultPrinter(UInt8 *data, ByteCount length, void *cookie)
  174. {
  175.     #pragma unused(cookie)
  176.     UInt32 row;
  177.     UInt32 col;
  178.     UInt32 rowCount;
  179.     UInt8 ch;
  180.  
  181.     rowCount = (length - 1) / 16 + 1;
  182.     for (row = 0; row < rowCount; row++) {
  183.         fprintf(gOutput, "      %04lX : ", row * 16);
  184.         for (col = 0; col < 16; col++) {
  185.             if ( (row * 16) + col < length ) {
  186.                 fprintf(gOutput, "%02X ", data[(row * 16) + col]);
  187.             } else {
  188.                 fprintf(gOutput, "   ");
  189.             }
  190.         }
  191.         for (col = 0; col < 16; col++) {
  192.             if ( (row * 16) + col < length ) {
  193.                 ch = data[(row * 16) + col];
  194.                 if ( ch < ' ' || ch == 127 ) {
  195.                     fprintf(gOutput, ".");
  196.                 } else {
  197.                     fprintf(gOutput, "%c", ch);
  198.                 }
  199.             }
  200.         }
  201.         fprintf(gOutput, "\n");
  202.     }
  203. }
  204.  
  205. static void DecimalPrinter(UInt8 *data, ByteCount length, void *cookie)
  206. {
  207.     #pragma unused(cookie)
  208.     
  209.     switch (length) {
  210.         case sizeof(SInt8):
  211.             fprintf(gOutput, "      value = %d\n", *((SInt8*) data));
  212.             break;
  213.         case sizeof(SInt16):
  214.             fprintf(gOutput, "      value = %ld\n", *((SInt16*) data));
  215.             break;
  216.         case sizeof(SInt32):
  217.             fprintf(gOutput, "      value = %ld\n", *((SInt32*) data));
  218.             break;
  219.         default:
  220.             fprintf(gOutput, "••• DecimalPrinter: Weird size preference data\n");
  221.             DefaultPrinter(data, length, nil);
  222.             break;
  223.     }
  224. }
  225.  
  226. static void PStringPrinter(UInt8 *data, ByteCount length, void *cookie)
  227. {
  228.     #pragma unused(cookie)
  229.     
  230.     if ((*data + 1) != length) {
  231.         fprintf(gOutput, "••• PStringPrinter: Weird size preference data\n");
  232.         DefaultPrinter(data, length, nil);
  233.     } else {
  234.         fprintf(gOutput, "      “\\p%#s”\n", data);
  235.     }
  236. }
  237.  
  238. static void CStringPrinter(UInt8 *data, ByteCount length, void *cookie)
  239. {
  240.     #pragma unused(cookie)
  241.     
  242.     if ((strlen((char *) data) + 1) != length) {
  243.         fprintf(gOutput, "••• CStringPrinter: Weird size preference data\n");
  244.         DefaultPrinter(data, length, nil);
  245.     } else {
  246.         fprintf(gOutput, "      “%s”\n", data);
  247.     }
  248. }
  249.  
  250. static void DateTimePrinter(UInt8 *data, ByteCount length, void *cookie)
  251. {
  252.     #pragma unused(cookie)
  253.     UInt32 dateTime;
  254.     Str255 dateStr;
  255.     Str255 timeStr;
  256.     
  257.     if (length != sizeof(UInt32)) {
  258.         fprintf(gOutput, "••• DateTimePrinter: Weird size preference data\n");
  259.         DefaultPrinter(data, length, nil);
  260.     } else {
  261.         dateTime = *((UInt32 *) data);
  262.         DateString(dateTime, shortDate, dateStr, nil);
  263.         TimeString(dateTime, true, timeStr, nil);
  264.         fprintf(gOutput, "      %#s, %#s\n", dateStr, timeStr);
  265.     }
  266. }
  267.  
  268. static void DeviceTypePrinter(UInt8 *data, ByteCount length, void *cookie)
  269. {
  270.     #pragma unused(cookie)
  271.     char *str;
  272.     Boolean printRaw;
  273.     UInt16 value;
  274.     
  275.     if (length != sizeof(UInt16)) {
  276.         fprintf(gOutput, "••• DeviceTypePrinter: Weird size preference data\n");
  277.         DefaultPrinter(data, length, nil);
  278.     } else {
  279.         printRaw = false;
  280.         value = *((UInt16 *) data);
  281.         switch ( value ) {
  282.             case kOTNoDeviceType: str = "kOTNoDeviceType"; break;
  283.             case kOTADEVDevice: str = "kOTADEVDevice"; break;
  284.             case kOTMDEVDevice: str = "kOTMDEVDevice"; break;
  285.             case kOTLocalTalkDevice: str = "kOTLocalTalkDevice"; break;
  286.             case kOTIRTalkDevice: str = "kOTIRTalkDevice"; break;
  287.             case kOTTokenRingDevice: str = "kOTTokenRingDevice"; break;
  288.             case kOTISDNDevice: str = "kOTISDNDevice"; break;
  289.             case kOTATMDevice: str = "kOTATMDevice"; break;
  290.             case kOTSMDSDevice: str = "kOTSMDSDevice"; break;
  291.             case kOTSerialDevice: str = "kOTSerialDevice"; break;
  292.             case kOTEthernetDevice: str = "kOTEthernetDevice"; break;
  293.             case kOTSLIPDevice: str = "kOTSLIPDevice"; break;
  294.             case kOTPPPDevice: str = "kOTPPPDevice"; break;
  295.             case kOTModemDevice: str = "kOTModemDevice"; break;
  296.             case kOTFastEthernetDevice: str = "kOTFastEthernetDevice"; break;
  297.             case kOTFDDIDevice: str = "kOTFDDIDevice"; break;
  298.             case kOTIrDADevice: str = "kOTIrDADevice"; break;
  299.             case kOTATMSNAPDevice: str = "kOTATMSNAPDevice"; break;
  300.             case kOTFibreChannelDevice: str = "kOTFibreChannelDevice"; break;
  301.             case kOTFireWireDevice: str = "kOTFireWireDevice"; break;
  302.             case kOTPseudoDevice: str = "kOTPseudoDevice"; break;
  303.             default: str = "unknown"; printRaw = true; break;
  304.         }
  305.         fprintf(gOutput, "      %s (%d)\n", str, value);
  306.         if (printRaw){
  307.             DefaultPrinter(data, length, nil);
  308.         }
  309.     }
  310. }
  311.  
  312. static Boolean UnpackTCPSearchList(const UInt8 *data, ByteCount length, OTCfgHSTFPrefs *searchListPref)
  313. {
  314.     const UInt8 *cursor;
  315.     MoreAssertQ(data != nil);
  316.     MoreAssertQ(searchListPref != nil);
  317.     
  318.     cursor = data;
  319.     if (cursor + sizeof(SInt8) <= data + length) {
  320.         searchListPref->fPrimaryInterfaceIndex = *cursor;
  321.         cursor += sizeof(SInt8);
  322.     }
  323.     if (cursor + *cursor + 1 <= data + length) {
  324.         BlockMoveData(cursor, searchListPref->fLocalDomainName, *cursor + 1);
  325.         cursor += (*cursor + 1);
  326.     }
  327.     if (cursor + *cursor + 1 <= data + length) {
  328.         BlockMoveData(cursor, searchListPref->admindomain, *cursor + 1);
  329.         cursor += (*cursor + 1);
  330.     }
  331.     return (cursor == data + length);
  332. }
  333.  
  334. static void TCPSearchListPrinter(UInt8 *data, ByteCount length, void *cookie)
  335. {
  336.     #pragma unused(cookie)
  337.     OTCfgHSTFPrefs searchListPref;
  338.     
  339.     if ( ! UnpackTCPSearchList(data, length, &searchListPref) ) {
  340.         fprintf(gOutput, "••• TCPSearchListPrinter: Weird size preference data\n");
  341.         DefaultPrinter(data, length, nil);
  342.     } else {
  343.         fprintf(gOutput, "      fPrimaryInterfaceIndex = %d\n", searchListPref.fPrimaryInterfaceIndex);
  344.         fprintf(gOutput, "      fLocalDomainName = “\\p%#s”\n", searchListPref.fLocalDomainName);
  345.         fprintf(gOutput, "      admindomain = “\\p%#s”\n", searchListPref.admindomain);
  346.     }
  347. }
  348.  
  349. static void TCPServersListPrinter(UInt8 *data, ByteCount length, void *cookie)
  350. {
  351.     #pragma unused(cookie)
  352.     SInt16 serverCount;
  353.     ItemCount serverIndex;
  354.     
  355.     serverCount = ((OTCfgIDNSPrefs *) data)->fCount;
  356.     if ( length < sizeof(SInt16) || length != (sizeof(SInt16) + serverCount * sizeof(InetHost))) {
  357.         fprintf(gOutput, "••• TCPSearchListPrinter: Weird size preference data\n");
  358.         DefaultPrinter(data, length, nil);
  359.     } else {
  360.         fprintf(gOutput, "      fCount = %d\n", serverCount);
  361.         for (serverIndex = 0; serverIndex < serverCount; serverIndex++) {
  362.             fprintf(gOutput, "        fAddressesList[%d] = %s\n", serverIndex,
  363.                     FormatInetHost((&((OTCfgIDNSPrefs *)data)->fAddressesList)[serverIndex]));
  364.         }
  365.     }
  366. }
  367.  
  368. static void TCPUnloadTypeAtrrPrinter(UInt8 *data, ByteCount length, void *cookie)
  369. {
  370.     #pragma unused(cookie)
  371.     SInt16 value;
  372.     char *name;
  373.  
  374.     if ( length != sizeof(SInt16) ) {
  375.         fprintf(gOutput, "••• TCPUnloadTypeAtrrPrinter: Weird size preference data\n");
  376.         DefaultPrinter(data, length, nil);
  377.     } else {
  378.         value = *((SInt16*)data);
  379.         switch ( value ) {
  380.             case 1: name = "kActiveLoadedOnDemand"; break;
  381.             case 2: name = "kActiveAlwaysLoaded"; break;
  382.             case 3: name = "kInactive"; break;
  383.             default: name = "unknown"; break;
  384.         }
  385.         fprintf(gOutput, "      %s (%d)\n", name, value);
  386.     }
  387. }
  388.  
  389. static Boolean UnpackOTCfgIITFPrefs(const UInt8 *data, ByteCount length, UInt8 **cursorPtr,
  390.                                         OTCfgIITFPrefs *unpacked, Str255 appleTalkZone)
  391. {
  392.     Boolean ok;
  393.     UInt8 *cursor;
  394.     
  395.     MoreAssertQ(data != nil);
  396.     MoreAssertQ(cursorPtr != nil);
  397.     MoreAssertQ(*cursorPtr >= data && *cursorPtr < data + length);
  398.     MoreAssertQ(unpacked != nil);
  399.     MoreAssertQ(appleTalkZone != nil);
  400.     
  401.     cursor = *cursorPtr;
  402.     ok = true;
  403.     unpacked->fCount = 0;
  404.  
  405.     if ( ok && (cursor + sizeof(UInt8) <= data + length) ) {
  406.         unpacked->fConfigMethod = *cursor;
  407.         cursor += sizeof(UInt8);
  408.     } else {
  409.         ok = false;
  410.     }
  411.     if ( ok && (cursor + sizeof(InetHost) <= data + length) ) {
  412.         BlockMoveData(cursor, &unpacked->fIPAddress, sizeof(InetHost));
  413.         cursor += sizeof(InetHost);
  414.     } else {
  415.         ok = false;
  416.     }
  417.     if ( ok && (cursor + sizeof(InetHost) <= data + length) ) {
  418.         BlockMoveData(cursor, &unpacked->fSubnetMask, sizeof(InetHost));
  419.         cursor += sizeof(InetHost);
  420.     } else {
  421.         ok = false;
  422.     }
  423.     if ( ok && (cursor + sizeof(SInt8) <= data + length) ) {
  424.         // OTCfgIITFPrefs only defines 1 byte of storage for fAppleTalkZone,
  425.         // so we have to return it in an extra Str255 parameter.
  426.         unpacked->fAppleTalkZone[0] = 0;
  427.         appleTalkZone[0] = *cursor;
  428.         cursor += sizeof(UInt8);
  429.     } else {
  430.         ok = false;
  431.     }
  432.  
  433.     // Who the hell thought putting a packed pascal string into the middle
  434.     // of a structure was a good idea!?!
  435.     
  436.     if ( ok && (cursor + appleTalkZone[0] <= data + length) ) {
  437.         BlockMoveData(cursor, &appleTalkZone[1], appleTalkZone[0]);
  438.         cursor += appleTalkZone[0];
  439.     } else {
  440.         ok = false;
  441.     }
  442.  
  443.     if ( ok && (cursor + 36 <= data + length) ) {
  444.         BlockMoveData(cursor, unpacked->part.path, 36);
  445.         cursor += 36;
  446.     } else {
  447.         ok = false;
  448.     }
  449.     if ( ok && (cursor + 32 <= data + length) ) {
  450.         BlockMoveData(cursor, unpacked->part.module, 32);
  451.         cursor += 32;
  452.     } else {
  453.         ok = false;
  454.     }
  455.     if ( ok && (cursor + sizeof(UInt32) <= data + length) ) {
  456.         BlockMoveData(cursor, &unpacked->part.framing, sizeof(UInt32));
  457.         cursor += sizeof(UInt32);
  458.     } else {
  459.         ok = false;
  460.     }
  461.     
  462.     *cursorPtr = cursor;
  463.     return ok;
  464. }
  465.  
  466. static void TCPPrefsPrinter(UInt8 *data, ByteCount length, void *cookie)
  467. {
  468.     #pragma unused(cookie)
  469.     UInt8 *cursor;
  470.     SInt16 prefCount;
  471.     SInt16 prefIndex;
  472.     OTCfgIITFPrefs prefData;
  473.     Str255 appleTalkZone;
  474.     
  475.     if ( length < sizeof(SInt16) ) {
  476.         fprintf(gOutput, "••• TCPPrefsPrinter: Weird size preference data\n");
  477.         DefaultPrinter(data, length, nil);
  478.     } else {
  479.         cursor = data;
  480.         prefCount = *((SInt16 *)cursor);
  481.         cursor += sizeof(SInt16);
  482.         
  483.         fprintf(gOutput, "      fCount = %d\n", prefCount);
  484.         for (prefIndex = 0; prefIndex < prefCount; prefIndex++) {
  485.             fprintf(gOutput, "        [%d]\n", prefIndex);
  486.             if ( UnpackOTCfgIITFPrefs(data, length, &cursor, &prefData, appleTalkZone) ) {
  487.                 fprintf(gOutput, "          fConfigMethod = %s (%d)\n", TCPConfigMethodToString(prefData.fConfigMethod), prefData.fConfigMethod);
  488.                 fprintf(gOutput, "          fIPAddress = %s\n", FormatInetHost( *((InetHost *) prefData.fIPAddress)));
  489.                 fprintf(gOutput, "          fSubnetMask = %s\n", FormatInetHost( *((InetHost *) prefData.fSubnetMask)));
  490.                 fprintf(gOutput, "          fAppleTalkZone = “%#s”\n", appleTalkZone);
  491.                 fprintf(gOutput, "          part.path = “%#s”\n", prefData.part.path);
  492.                 fprintf(gOutput, "          part.module = “%#s”\n", prefData.part.module);
  493.                 fprintf(gOutput, "          part.framing = %08x\n", prefData.part.framing);
  494.             } else {
  495.                 fprintf(gOutput, "••• TCPPrefsPrinter: Error parsing data data\n");
  496.                 DefaultPrinter(data, length, nil);
  497.                 break;
  498.             }
  499.         }
  500.         if (prefIndex == prefCount) {
  501.             if (cursor != data + length) {
  502.                 fprintf(gOutput, "••• TCPPrefsPrinter: Didn't consume all the data\n");
  503.                 DefaultPrinter(data, length, nil);
  504.             }
  505.         } else {
  506.             fprintf(gOutput, "••• TCPPrefsPrinter: Didn't iterate far enough\n");
  507.             DefaultPrinter(data, length, nil);
  508.         }
  509.     }
  510. }
  511.  
  512. static void DomainListPrinter(UInt8 *data, ByteCount length, void *cookie)
  513. {
  514.     #pragma unused(cookie)
  515.     UInt8 *cursor;
  516.     SInt16 domainCount;
  517.     SInt16 domainIndex;
  518.     Str255 thisDomain;
  519.     
  520.     if ( length < sizeof(SInt16) ) {
  521.         fprintf(gOutput, "••• DomainListPrinter: Weird size preference data\n");
  522.         DefaultPrinter(data, length, nil);
  523.     } else {
  524.         cursor = data;
  525.         domainCount = *((SInt16 *)cursor);
  526.         cursor += sizeof(SInt16);
  527.         fprintf(gOutput, "      fCount = %d\n", domainCount);
  528.         for (domainIndex = 0; domainIndex < domainCount; domainIndex++) {
  529.             if ( cursor + sizeof(UInt8) <= data + length ) {
  530.                 thisDomain[0] = *cursor;
  531.                 cursor += 1;
  532.                 if ( cursor + thisDomain[0] <= data + length ) {
  533.                     BlockMoveData(cursor, &thisDomain[1], thisDomain[0]);
  534.                     cursor += thisDomain[0];
  535.                     fprintf(gOutput, "        [%d] = “%#s”\n", domainIndex, thisDomain);
  536.                 } else {
  537.                     break;
  538.                 }
  539.             } else {
  540.                 break;
  541.             }
  542.         }
  543.         if (domainIndex == domainCount) {
  544.             if (cursor != data + length) {
  545.                 fprintf(gOutput, "••• DomainListPrinter: Didn't consume all the data\n");
  546.                 DefaultPrinter(data, length, nil);
  547.             }
  548.         } else {
  549.             fprintf(gOutput, "••• DomainListPrinter: Didn't iterate far enough\n");
  550.             DefaultPrinter(data, length, nil);
  551.         }
  552.     }
  553. }
  554.  
  555. static void RouterListPrinter(UInt8 *data, ByteCount length, void *cookie)
  556. {
  557.     #pragma unused(cookie)
  558.     SInt16 routeCount;
  559.     SInt16 routeIndex;
  560.     OTCfgIRTEPrefs *prefData;
  561.     
  562.     prefData = (OTCfgIRTEPrefs *)data;
  563.     routeCount = prefData->fCount;
  564.     if ( length < sizeof(SInt16) || ( length != sizeof(SInt16) + routeCount * sizeof(OTCfgIRTEEntry)) ) {
  565.         fprintf(gOutput, "••• RouterListPrinter: Weird size preference data\n");
  566.         DefaultPrinter(data, length, nil);
  567.     } else {
  568.         fprintf(gOutput, "      fCount = %d\n", routeCount);
  569.         for (routeIndex = 0; routeIndex < routeCount; routeIndex++) {
  570.             fprintf(gOutput, "      fList[%d].fToHost = %s\n", routeIndex, FormatInetHost(prefData->fList[routeIndex].fToHost));
  571.             fprintf(gOutput, "      fList[%d].fViaHost = %s\n", routeIndex, FormatInetHost(prefData->fList[routeIndex].fViaHost));
  572.             fprintf(gOutput, "      fList[%d].fLocal = %d\n", routeIndex, prefData->fList[routeIndex].fLocal);
  573.             fprintf(gOutput, "      fList[%d].fHost = %d\n", routeIndex, prefData->fList[routeIndex].fHost);
  574.         }
  575.     }
  576. }
  577.  
  578. static void UserLevelPrinter(UInt8 *data, ByteCount length, void *cookie)
  579. {
  580.     #pragma unused(cookie)
  581.     SInt16 value;
  582.     char *name;
  583.  
  584.     if ( length != sizeof(SInt16) ) {
  585.         fprintf(gOutput, "••• UserLevelPrinter: Weird size preference data\n");
  586.         DefaultPrinter(data, length, nil);
  587.     } else {
  588.         value = *((SInt16*)data);
  589.         switch ( value ) {
  590.             case 1: name = "kBasicMode"; break;
  591.             case 2: name = "kAdvancedMode"; break;
  592.             case 3: name = "kAdminMode"; break;
  593.             default: name = "unknown"; break;
  594.         }
  595.         fprintf(gOutput, "      %s (%d)\n", name, value);
  596.     }
  597. }
  598.  
  599. typedef void (*PrinterProc)(UInt8 *data, ByteCount length, void *cookie);
  600.  
  601. static void GetPrefTypeInfo(OSType prefType, char **userVisibleString, PrinterProc *printerProc, void **printerCookie)
  602. {
  603.     *userVisibleString = "unknown";
  604.     *printerProc = DefaultPrinter;
  605.     *printerCookie = nil;
  606.  
  607.     switch (prefType) {
  608.  
  609.         // Backward Compatibility Preferences
  610.         
  611.         case 'resn':
  612.             *userVisibleString = "Backward Compatibility Resource Name";
  613.             *printerProc = PStringPrinter;
  614.             break;
  615.         
  616.         case 'resi':
  617.             *userVisibleString = "Backward Compatibility Resource ID";
  618.             *printerProc = DecimalPrinter;
  619.             break;
  620.             
  621.         case 'time':
  622.             *userVisibleString = "Backward Compatibility Timestamp";
  623.             *printerProc = DateTimePrinter;
  624.             break;
  625.  
  626.         case 'ccfg':
  627.             *userVisibleString = "kSelectedConfigType";
  628.             *printerProc = DecimalPrinter;
  629.             break;
  630.             
  631.         // Generic
  632.  
  633.         case 'pnam':
  634.             *userVisibleString = "Preference Name";
  635.             *printerProc = PStringPrinter;
  636.             break;
  637.  
  638.         case kOTCfgTypeStruct:
  639.             *userVisibleString = "kOTCfgTypeStruct";
  640.             break;
  641.         case kOTCfgTypeElement:
  642.             *userVisibleString = "kOTCfgTypeElement";
  643.             break;
  644.         case kOTCfgTypeVector:
  645.             *userVisibleString = "kOTCfgTypeVector";
  646.             break;
  647.         case kCfgTypefree:
  648.             *userVisibleString = "kCfgTypefree";
  649.             break;
  650.  
  651.         // Common to all the control panels
  652.         
  653.         case kOTCfgTypeWindowPosition:
  654.             *userVisibleString = "kOTCfgTypeWindowPosition";
  655.             break;
  656. //        case kInfraredWindowPosAttr:
  657. //            *userVisibleString = "kInfraredWindowPosAttr";
  658. //            break;
  659. //        case kTCPWindowPositionAttr:
  660. //            *userVisibleString = "kTCPWindowPositionAttr";
  661. //            break;
  662.         case kOTCfgTypeAppleTalkVersion:
  663.             *userVisibleString = "kOTCfgTypeAppleTalkVersion";
  664.             *printerProc = DecimalPrinter;
  665.             break;
  666. //        case kCVRSResType:
  667. //            *userVisibleString = "kCVRSResType";
  668. //            break;
  669. //        case kTCPVersionAttr:
  670. //            *userVisibleString = "kTCPVersionAttr";
  671. //            break;
  672.         case kOTCfgTypeAppleTalkPort:
  673.             *userVisibleString = "kOTCfgTypeAppleTalkPort";
  674.             *printerProc = PStringPrinter;
  675.             break;
  676. //        case kPORTResType:
  677. //            *userVisibleString = "kPORTResType";
  678. //            break;
  679. //        case kTCPPortAttr:
  680. //            *userVisibleString = "kTCPPortAttr";
  681. //            break;
  682. //        case kRAConfigTypePort:
  683. //            *userVisibleString = "kRAConfigTypePort";
  684. //            break;
  685.         case 'cnam':
  686.             *userVisibleString = "kResourceCount";
  687.             break;
  688. //        case kATResourceCount:
  689. //            *userVisibleString = "kATResourceCount";
  690. //            break;
  691. //        case kTCPResourceCount:
  692. //            *userVisibleString = "kTCPResourceCount";
  693. //            break;
  694. //        case kModemResourceCount:
  695. //            *userVisibleString = "kModemResourceCount";
  696. //            break;
  697. //        case kRAConfigNameType:
  698. //            *userVisibleString = "kRAConfigNameType";
  699. //            break;
  700.         case kOTCfgTypeAppleTalkProtocol:
  701.             *userVisibleString = "kOTCfgTypeAppleTalkProtocol";
  702.             *printerProc = CStringPrinter;
  703.             break;
  704. //        case kTCPProtocolAttr:
  705. //            *userVisibleString = "kTCPProtocolAttr";
  706. //            break;
  707.         case kOTCfgTypeAppleTalkPassword:
  708.             *userVisibleString = "kOTCfgTypeAppleTalkPassword";
  709.             break;
  710. //        case kTCPPasswordAttr:
  711. //            *userVisibleString = "kTCPPasswordAttr";
  712. //            break;
  713.         case kOTCfgTypeUserLevel:
  714.             *userVisibleString = "kOTCfgTypeUserLevel";
  715.             *printerProc = UserLevelPrinter;
  716.             break;
  717. //        case kUserModeResType:
  718. //            *userVisibleString = "kUserModeResType";
  719. //            break;
  720. //        case kTCPUserLevelAttr:
  721. //            *userVisibleString = "kTCPUserLevelAttr";
  722. //            break;
  723. //        case kTCPSelectedConfigType:
  724. //            *userVisibleString = "kTCPSelectedConfigType";
  725. //            break;
  726. //        case kModemSelectedConfigType:
  727. //            *userVisibleString = "kModemSelectedConfigType";
  728. //            break;
  729. //        case kRemoteSelectedConfigType:
  730. //            *userVisibleString = "kRemoteSelectedConfigType";
  731. //            break;
  732.  
  733.         // AppleTalk
  734.         
  735.         case kOTCfgTypeAppleTalkPrefs:
  736.             *userVisibleString = "kOTCfgTypeAppleTalkPrefs";
  737.             break;
  738.         case kOTCfgTypeAppleTalkLocks:
  739.             *userVisibleString = "kOTCfgTypeAppleTalkLocks";
  740.             break;
  741.         case kOTCfgTypeAppleTalkPortFamily:
  742.             *userVisibleString = "kOTCfgTypeAppleTalkPortFamily";
  743.             break;
  744.             
  745.         // Infrared
  746.  
  747. //        case kInfraredPrefsAttr:
  748. //            *userVisibleString = "kInfraredPrefsAttr";
  749. //            break;
  750.         case kOTCfgTypeInfraredGlobal:
  751.             *userVisibleString = "kOTCfgTypeInfraredGlobal";
  752.             break;
  753.             
  754.         // TCP/IP
  755.  
  756.         case kOTCfgTypeTCPalis:
  757.             *userVisibleString = "kOTCfgTypeTCPalis";
  758.             break;
  759.         case kOTCfgTypeTCPdcid:
  760.             *userVisibleString = "kOTCfgTypeTCPdcid";
  761.             break;
  762.         case kOTCfgTypeTCPdtyp:
  763.             *userVisibleString = "kOTCfgTypeTCPdtyp";
  764.             *printerProc = DeviceTypePrinter;
  765.             break;
  766. //        case kIDNSResType:
  767. //            *userVisibleString = "kIDNSResType";
  768. //            break;
  769. //        case kIHSTResType:
  770. //            *userVisibleString = "kIHSTResType";
  771. //            break;
  772. //        case kIITFResType:
  773. //            *userVisibleString = "kIITFResType";
  774. //            break;
  775. //        case kARAResType:
  776. //            *userVisibleString = "kARAResType";
  777. //            break;
  778. //        case kIRTEResType:
  779. //            *userVisibleString = "kIRTEResType";
  780. //            break;
  781. //        case kISDMResType:
  782. //            *userVisibleString = "kISDMResType";
  783. //            break;
  784. //        case kSTNGResType:
  785. //            *userVisibleString = "kSTNGResType";
  786. //            break;
  787. //        case kUNLDResType:
  788. //            *userVisibleString = "kUNLDResType";
  789. //            break;
  790.         case kOTCfgTypeTCPDevType:
  791.             *userVisibleString = "kOTCfgTypeTCPDevType";
  792.             break;
  793.         case kOTCfgTypeTCPPrefs:
  794.             *userVisibleString = "kOTCfgTypeTCPPrefs";
  795.             *printerProc = TCPPrefsPrinter;
  796.             break;
  797.         case kOTCfgTypeTCPServersList:
  798.             *userVisibleString = "kOTCfgTypeTCPServersList";
  799.             *printerProc = TCPServersListPrinter;
  800.             break;
  801.         case kOTCfgTypeTCPSearchList:
  802.             *userVisibleString = "kOTCfgTypeTCPSearchList";
  803.             *printerProc = TCPSearchListPrinter;
  804.             break;
  805.         case kOTCfgTypeTCPRoutersList:
  806.             *userVisibleString = "kOTCfgTypeTCPRoutersList";
  807.             *printerProc = RouterListPrinter;
  808.             break;
  809.         case kOTCfgTypeTCPDomainsList:
  810.             *userVisibleString = "kOTCfgTypeTCPDomainsList";
  811.             *printerProc = DomainListPrinter;
  812.             break;
  813.         case kOTCfgTypeTCPLocks:
  814.             *userVisibleString = "kOTCfgTypeTCPLocks";
  815.             break;
  816.         case kOTCfgTypeTCPUnloadType:
  817.             *userVisibleString = "kOTCfgTypeTCPUnloadType";
  818.             *printerProc = TCPUnloadTypeAtrrPrinter;
  819.             break;
  820.  
  821.         // Modem
  822.         
  823.         case kOTCfgTypeModemModem:
  824.             *userVisibleString = "kOTCfgTypeModemModem";
  825.             break;
  826.         case kOTCfgTypeModemLocks:
  827.             *userVisibleString = "kOTCfgTypeModemLocks";
  828.             break;
  829.         case kOTCfgTypeModemAdminPswd:
  830.             *userVisibleString = "kOTCfgTypeModemAdminPswd";
  831.             break;
  832.         case kOTCfgTypeModemApp:
  833.             *userVisibleString = "kOTCfgTypeModemApp";
  834.             break;
  835.             
  836.         // Remote Access
  837.  
  838.         case kOTCfgTypeRemoteARAP:
  839.             *userVisibleString = "kOTCfgTypeRemoteARAP";
  840.             break;
  841.         case kOTCfgTypeRemoteAddress:
  842.             *userVisibleString = "kOTCfgTypeRemoteAddress";
  843.             break;
  844.         case kOTCfgTypeRemoteChat:
  845.             *userVisibleString = "kOTCfgTypeRemoteChat";
  846.             break;
  847.         case kOTCfgTypeRemoteDialing:
  848.             *userVisibleString = "kOTCfgTypeRemoteDialing";
  849.             break;
  850.         case kOTCfgTypeRemoteExtAddress:
  851.             *userVisibleString = "kOTCfgTypeRemoteExtAddress";
  852.             break;
  853.         case kOTCfgTypeRemoteClientLocks:
  854.             *userVisibleString = "kOTCfgTypeRemoteClientLocks";
  855.             break;
  856.         case kOTCfgTypeRemoteClientMisc:
  857.             *userVisibleString = "kOTCfgTypeRemoteClientMisc";
  858.             break;
  859.         case kOTCfgTypeRemoteConnect:
  860.             *userVisibleString = "kOTCfgTypeRemoteConnect";
  861.             break;
  862.         case kOTCfgTypeRemoteUser:
  863.             *userVisibleString = "kOTCfgTypeRemoteUser";
  864.             break;
  865.         case kOTCfgTypeRemoteDialAssist:
  866.             *userVisibleString = "kOTCfgTypeRemoteDialAssist";
  867.             break;
  868.         case kOTCfgTypeRemoteIPCP:
  869.             *userVisibleString = "kOTCfgTypeRemoteIPCP";
  870.             break;
  871.         case kOTCfgTypeRemoteLCP:
  872.             *userVisibleString = "kOTCfgTypeRemoteLCP";
  873.             break;
  874.         case kOTCfgTypeRemoteLogOptions:
  875.             *userVisibleString = "kOTCfgTypeRemoteLogOptions";
  876.             break;
  877.         case kOTCfgTypeRemotePassword:
  878.             *userVisibleString = "kOTCfgTypeRemotePassword";
  879.             break;
  880.         case kOTCfgTypeRemoteServerLocks:
  881.             *userVisibleString = "kOTCfgTypeRemoteServerLocks";
  882.             break;
  883.         case kOTCfgTypeRemoteServer:
  884.             *userVisibleString = "kOTCfgTypeRemoteServer";
  885.             break;
  886.         case kOTCfgTypeRemoteUserMode:
  887.             *userVisibleString = "kOTCfgTypeRemoteUserMode";
  888.             break;
  889.         case kOTCfgTypeRemoteX25:
  890.             *userVisibleString = "kOTCfgTypeRemoteX25";
  891.             break;
  892.         case kOTCfgTypeRemoteApp:
  893.             *userVisibleString = "kOTCfgTypeRemoteApp";
  894.             break;
  895.  
  896.         default:
  897.             // do nothing
  898.             break;
  899.     }
  900. }
  901.  
  902. /////////////////////////////////////////////////////////////////
  903. #pragma mark ----- Core Implementation -----
  904.  
  905. static OSStatus DumpPref(CfgEntityAccessID prefsRefNum, prefType, PrinterProc printerProc, void *printerCookie)
  906. {
  907.     OSStatus err;
  908.     ByteCount prefSize;
  909.     UInt8 *prefData;
  910.     
  911.     prefData = nil;
  912.     
  913.     err = OTCfgGetPrefsSize(prefsRefNum, prefType, &prefSize);
  914.     if (err == noErr && prefSize != 0) {
  915.         prefData = (UInt8*) NewPtr(prefSize);
  916.         err = MemError();
  917.         if (err == noErr) {
  918.             MoreAssertQ(prefData != nil);
  919.             err = OTCfgGetPrefs(prefsRefNum, prefType, prefData, prefSize);
  920.         }
  921.         if (err == noErr) {
  922.             printerProc(prefData, prefSize, printerCookie);
  923.         }
  924.     }
  925.     
  926.     if (prefData != nil) {
  927.         DisposePtr( (Ptr) prefData );
  928.         MoreAssertQ(MemError() == noErr);
  929.     }
  930.  
  931.     return err;
  932. }
  933.  
  934. // static CfgPrefsHeader gPrefsTOCs[40];
  935.  
  936. static OSStatus DumpEntity(CfgDatabaseRef ref, CfgEntityRef entity)
  937. {
  938.     OSStatus err;
  939.     OSStatus err2;
  940.     CfgEntityAccessID accessID;
  941.     ItemCount prefsTOCCount;
  942.     ItemCount i;
  943.     char *userVisibleString;
  944.     PrinterProc printerProc;
  945.     void *printerCookie;
  946.     CfgPrefsHeader *prefsTOCs;
  947.     
  948.     prefsTOCs = nil;
  949.     
  950.     err = OTCfgOpenPrefs(ref, &entity, false, &accessID);
  951.     if (err == noErr) {
  952.         err = OTCfgGetPrefsTOCCount(accessID, &prefsTOCCount);
  953.         if (err == noErr) {
  954.             prefsTOCs = (CfgPrefsHeader *) NewPtr( prefsTOCCount * sizeof(CfgPrefsHeader));
  955.             err = MemError();
  956.         }
  957.         if (err == noErr) {
  958.             err = OTCfgGetPrefsTOC(accessID, &prefsTOCCount, prefsTOCs);
  959.         }
  960.         if (err == noErr) {    
  961.             for (i = 0; i < prefsTOCCount; i++) {
  962.                 GetPrefTypeInfo(prefsTOCs[i].fType, &userVisibleString, &printerProc, &printerCookie);
  963.                 fprintf(gOutput, "    Preference\n");
  964.                 fprintf(gOutput, "      fSize = %hd\n", prefsTOCs[i].fSize);
  965.                 fprintf(gOutput, "      fVersion = %hd\n", prefsTOCs[i].fVersion);
  966.                 fprintf(gOutput, "      fType = '%4.4s' “%s”\n", &prefsTOCs[i].fType, userVisibleString);
  967.                 err = DumpPref(accessID, prefsTOCs[i].fType, printerProc, printerCookie);
  968.                 if (err != noErr) {
  969.                     break;
  970.                 }
  971.             }
  972.         }
  973.         
  974.         err2 = OTCfgClosePrefs(accessID);
  975.         if (err == noErr) {
  976.             err = err2;
  977.         }
  978.     }
  979.     if (prefsTOCs != nil) {
  980.         DisposePtr( (Ptr) prefsTOCs );
  981.         MoreAssertQ(MemError() == noErr);
  982.     }
  983.     return err;
  984. }
  985.  
  986. // static CfgEntityRef gEntityRefs[20];
  987. // static CfgEntityInfo gEntityInfos[20];
  988.  
  989. static OSStatus DumpArea(CfgDatabaseRef ref, CfgAreaID thisArea)
  990. {
  991.     OSStatus err;
  992.     OSStatus err2;
  993.     ItemCount entityCount;
  994.     Str255 entityName;
  995.     ItemCount i;
  996.     CfgEntityRef *entityRefs;
  997.     CfgEntityInfo *entityInfos;
  998.     
  999.     entityRefs = nil;
  1000.     entityInfos = nil;
  1001.     
  1002.     err = OTCfgOpenArea(ref, thisArea);
  1003.     if (err == noErr) {
  1004.         err = OTCfgGetEntitiesCount(ref, thisArea, kCfgClassAnyEntity, kCfgTypeAnyEntity, &entityCount);
  1005.         if (err == noErr) {
  1006.             entityRefs = (CfgEntityRef *) NewPtr( entityCount * sizeof(CfgEntityRef));
  1007.             err = MemError();
  1008.         }
  1009.         if (err == noErr) {
  1010.             entityInfos = (CfgEntityInfo *) NewPtr( entityCount * sizeof(CfgEntityInfo));
  1011.             err = MemError();
  1012.         }
  1013.         err = OTCfgGetEntitiesList(ref, thisArea,
  1014.                                  kCfgClassAnyEntity,
  1015.                                  kCfgTypeAnyEntity,
  1016.                                  &entityCount,
  1017.                                  entityRefs,
  1018.                                  entityInfos);
  1019.         if (err == noErr) {
  1020.             for (i = 0; i < entityCount; i++) {
  1021.                 OTCfgGetEntityName(&entityRefs[i], entityName);
  1022.                 fprintf(gOutput, "  Dumping entity “%#s”\n", entityName);
  1023.                 fprintf(gOutput, "    CfgEntityRef\n");
  1024.                 fprintf(gOutput, "      fLoc = %ld\n", entityRefs[i].fLoc);
  1025.                 fprintf(gOutput, "      fReserved = %ld\n", entityRefs[i].fReserved);
  1026.                 fprintf(gOutput, "      fID = %#s\n", entityRefs[i].fID);
  1027.                 fprintf(gOutput, "    CfgEntityInfo\n");
  1028.                 fprintf(gOutput, "      fClass = '%4.4s' “%s”\n", &entityInfos[i].fClass, ClassToString(entityInfos[i].fClass));
  1029.                 fprintf(gOutput, "      fType  = '%4.4s' “%s”\n", &entityInfos[i].fType,  TypeToString(entityInfos[i].fType));
  1030.                 fprintf(gOutput, "      fIcon\n");
  1031.                 fprintf(gOutput, "        fFile\n");
  1032.                 fprintf(gOutput, "          vRefNum = %hd\n", entityInfos[i].fIcon.fFile.vRefNum);
  1033.                 fprintf(gOutput, "          parID   = %ld\n", entityInfos[i].fIcon.fFile.parID);
  1034.                 fprintf(gOutput, "          name    = %#s\n", entityInfos[i].fIcon.fFile.name);
  1035.                 fprintf(gOutput, "        fResID  = %hd\n", entityInfos[i].fIcon.fResID);
  1036.                 
  1037.                 err = DumpEntity(ref, entityRefs[i]);
  1038.                 if (err != noErr) {
  1039.                     break;
  1040.                 }
  1041.             }
  1042.         }
  1043.         
  1044.         err2 = OTCfgCloseArea(ref, thisArea);
  1045.         if (err == noErr) {
  1046.             err = err2;
  1047.         }
  1048.     }
  1049.  
  1050.     if (entityRefs != nil) {
  1051.         DisposePtr( (Ptr) entityRefs);
  1052.         MoreAssertQ(MemError() == noErr);
  1053.     }
  1054.     if (entityInfos != nil) {
  1055.         DisposePtr( (Ptr) entityInfos);
  1056.         MoreAssertQ(MemError() == noErr);
  1057.     }
  1058.     return err;
  1059. }
  1060.  
  1061. static OSStatus DumpDatabaseToFile(void)
  1062. {
  1063.     OSStatus err;
  1064.     OSStatus err2;
  1065.     CfgDatabaseRef ref;
  1066.     ItemCount areaCount;
  1067.     CfgAreaID currentArea;
  1068.     ItemCount i;
  1069.     CfgAreaID *areas;
  1070.     Str255 *areaNames;
  1071.     
  1072.     areas = nil;
  1073.     areaNames = nil;
  1074.     
  1075.     err = OTCfgOpenDatabase(&ref);
  1076.     if (err == noErr) {
  1077.         err = OTCfgGetAreasCount(ref, &areaCount);
  1078.         if (err == noErr) {
  1079.             areas = (CfgAreaID *) NewPtr( areaCount * sizeof(CfgAreaID) );
  1080.             err = MemError();
  1081.         }
  1082.         if (err == noErr) {
  1083.             areaNames = (Str255 *) NewPtr( areaCount * sizeof(Str255) );
  1084.             err = MemError();
  1085.         }
  1086.         if (err == noErr) {
  1087.             err = OTCfgGetAreasList(ref, &areaCount, areas, areaNames);
  1088.         }
  1089.         
  1090.         if (err == noErr) {
  1091.             err = OTCfgGetCurrentArea(ref, ¤tArea);
  1092.         }
  1093.         
  1094.         if (err == noErr) {
  1095.             for (i = 0; i < areaCount; i++) {
  1096.                 fprintf(gOutput, "Dumping area %ld “%#s”\n", areas[i], areaNames[i]);
  1097.                 if ( OTCfgIsSameAreaID(currentArea, areas[i]) ) {
  1098.                     fprintf(gOutput, "  <current area>\n");
  1099.                 }
  1100.                 err = DumpArea(ref, areas[i]);
  1101.                 if (err != noErr) {
  1102.                     break;
  1103.                 }
  1104.             }
  1105.         }
  1106.     
  1107.         err2 = OTCfgCloseDatabase(&ref);
  1108.         if (err == noErr) {
  1109.             err = err2;
  1110.         }
  1111.     }
  1112.     if (areas != nil) {
  1113.         DisposePtr( (Ptr) areas);
  1114.         MoreAssertQ(MemError() == noErr);
  1115.     }
  1116.     if (areaNames != nil) {
  1117.         DisposePtr( (Ptr) areaNames);
  1118.         MoreAssertQ(MemError() == noErr);
  1119.     }
  1120.     return err;
  1121. }
  1122.  
  1123. static void InitToolbox(void)
  1124. {
  1125.     InitGraf(&qd.thePort);
  1126.     InitFonts();
  1127.     InitWindows();
  1128.     InitMenus();
  1129.     TEInit();
  1130.     InitDialogs(nil);
  1131.     MaxApplZone();
  1132.     MoreMasters();
  1133.     MoreMasters();
  1134.     MoreMasters();
  1135. }
  1136.  
  1137. extern void main(void)
  1138. {
  1139.     OSStatus err;
  1140.     StandardFileReply reply;
  1141.  
  1142.     InitToolbox();
  1143.  
  1144.     StandardPutFile("\pSave Network Setup database as text:", "\pNetworkSetup.txt", &reply);
  1145.     if (reply.sfGood) {
  1146.         (void) FSpDelete(&reply.sfFile);
  1147.         gOutput = FSp_fopen(&reply.sfFile, "w");
  1148.         if (gOutput == nil) {
  1149.             err = -1;
  1150.         }
  1151.         if (err == noErr) {
  1152.             err = DumpDatabaseToFile();
  1153.  
  1154.             (void) fclose(gOutput);
  1155.         }
  1156.         if (err != noErr) {
  1157.             printf("Failed with error %ld.\n", err);
  1158.         }
  1159.         
  1160.     }
  1161. }